#include "cengine.h"
#include "../win32/windowsutils.h"

namespace NEngine {

// ------------------------------------------------------------------------------------------------
// Listen to input
// ------------------------------------------------------------------------------------------------
void CEngine::Listen() {
    ASSERT_(listinit, "Listener did not initialize");
    kill = ilistener.Listen();
}

// ------------------------------------------------------------------------------------------------
// Update the scene
// ------------------------------------------------------------------------------------------------
void CEngine::Update() {
    ASSERT_(d3dinit, "D3D is not initialized");
    direct3d.Update();
}

// ------------------------------------------------------------------------------------------------
// Render the scene
// ------------------------------------------------------------------------------------------------
void CEngine::Render() {
    ASSERT_(d3dinit, "D3D did not initialize");
    direct3d.Render();
}

// ------------------------------------------------------------------------------------------------
// Load the resources in the resource directory
// ------------------------------------------------------------------------------------------------
bool CEngine::LoadResources() {
    // -- get the root resource path
    std::wstring respath = GetEnvironmentVariable("rpath");
    respath += L"\\*.txt";

    CDynamicArray<std::wstring> files = GetFilesInPath(respath, true);

    // -- pass the files to the importers
    importer.SetFile(files);
    limporter.SetFile(files);

    return true;
}

// ------------------------------------------------------------------------------------------------
// Create the initial camera in the scene
// ------------------------------------------------------------------------------------------------
void CEngine::CreateInitialCamera() {
    // -- create initial cameras 
    // -- call it the origin camera
    Matrix4x4 world = Identity();
    Vector4 at(0.0f, 0.0f, 1.0f);
    Vector4 pos(0.0f, 0.0f, 0.0f);
    Vector4 up(0.0f, 1.0f, 0.0f);
    CCamera ocam;
    ocam.SetCamera(at, up, pos);
    ocam.SetHand(CCamera::eRightHand);
    cams.Append(ocam);
    curcam = &cams[0];
}

// ================================================================================================
// Initialize the engine
// ================================================================================================
void CEngine::Init(bool wireframe) {
    // -- initialize the window
    if(FAILED(window.InitWindow(width, height))) 
        ASSERT_(false, "Failed to initialize the window");

    wininit = true;

    // -- load resources
    LoadResources();

    //$$$NAB temporary until we build cameras
    CreateInitialCamera();

    // -- build data from the files
    importer.Import();
    limporter.Import();

    lightbuilder.BuildLights(limporter.GetObjects(), cams, lviews);

    // -- initialize the direct3d engine
    direct3d.Init(importer.GetObjects(), lightbuilder.GetConstLightBuffer(), curcam, 
                  lviews, window.GetWinHandle(), window.GetRect(), wireframe);

    ilistener.SetRect(window.GetRect());

    ilistener.SetCamera(curcam, cams.GetSize());

    d3dinit = true;
}

// ================================================================================================
// Run the engine
// ================================================================================================
MSG CEngine::Run() {
    // main message loop
    MSG msg = {0};
    while(WM_QUIT != msg.message && !kill) {
        if( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else {
            // -- listen to input
            Listen();

            // -- update the scene
            Update();

            // -- render the scene
            Render();
        }
    }

    return msg;
}



} // namespace NEngine
